package org.tgcloud.group.service.manager.project;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.tgcloud.group.core.*;
import org.tgcloud.group.core.ExportUtils.ExcelUtils;
import org.tgcloud.group.entity.*;
import org.tgcloud.group.repository.*;
import org.tgcloud.group.service.manager.notify.NotifyService;
import org.tgcloud.group.web.controller.dto.project.file.ProjectFileDTO;
import org.springframework.http.MediaType;
import org.tgcloud.group.web.controller.req.project.file.FileIdReq;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author: zhy
 * @Created: 2025-09-05-上午11:01
 * @Description:
 */
@Service
public class FileManageService {

    @Autowired
    private ProjectFileMapper fileMapper;

    @Autowired
    private MjProjectMapper projectMapper;

    @Autowired
    private SysLabelValueMapper sysLabelValueMapper;

    @Autowired
    private MjNormalUserMapper normalUserMapper;

    @Autowired
    private MjBusinessPersonMapper businessPersonMapper;

    @Autowired
    private SysManagerUserMapper managerUserMapper;

    @Autowired
    private MjProjectStageMapper projectStageMapper;

    @Autowired
    private MjProjectStageLogMapper mjProjectStageLogMapper;


    @Autowired
    private NotifyService notifyService;

    public APPResultMessage<Object, ProjectFileDTO> getProjectFileList(Integer pageNum, Integer pageSize, Integer projectId, String keyword, String fileType, Short rejectStatus,
                                                                       Long createStartTime, Long createEndTime, Long rejectStartTime, Long rejectEndTime,Integer stageId) {


        List<Integer> fileTypeList = null;
        if(ObjectUtils.isNotEmpty(fileType)){
            fileTypeList = Arrays.stream(fileType.split(","))
                    .map(Integer::valueOf)
                    .collect(Collectors.toList());
        }
        Integer resultStageId = null;
        if(ObjectUtils.isNotEmpty(fileTypeList)){
            if(fileTypeList.contains(5122) || fileTypeList.contains(5123)){
                resultStageId = stageId;
            }
        }
        if (pageNum != null && pageSize != null){
            PageHelper.startPage(pageNum, pageSize);
            List<ProjectFileDTO> list = fileMapper.selectManageListByKeyword(projectId, keyword, fileTypeList, rejectStatus,resultStageId,
                    createStartTime != null ? new Date(createStartTime) : null, createEndTime != null ? new Date(createEndTime) : null,
                    rejectStartTime != null ? new Date(rejectStartTime) : null, rejectEndTime != null ? new Date(rejectEndTime) : null);
            PageInfo<ProjectFileDTO> tables = new PageInfo<>(list);
            for (ProjectFileDTO dto : tables.getList()){
                dto.setCreatePerson(getUsernameByIdAndUserType(dto.getUserId(), dto.getUserType()));
                if (dto.getRejectUserId() != null){
                    dto.setRejectPerson(getUsernameByIdAndUserType(dto.getRejectUserId(), dto.getRejectUserType()));
                }
            }
            ResultMessage result = ResultMessage.builder().setList(tables.getList()).setAllPageNumber(tables.getPages()).setCount(tables.getTotal());
            APPResultMessage<Object, ProjectFileDTO> message = APPResultMessage.getSuccessMessage();
            message.setResult(result);
            return message;
        }else {
            List<ProjectFileDTO> list = fileMapper.selectManageListByKeyword(projectId, keyword, fileTypeList, rejectStatus,resultStageId,
                    createStartTime != null ? new Date(createStartTime) : null, createEndTime != null ? new Date(createEndTime) : null,
                    rejectStartTime != null ? new Date(rejectStartTime) : null, rejectEndTime != null ? new Date(rejectEndTime) : null);
            ResultMessage result = ResultMessage.builder().setList(list);
            for (ProjectFileDTO dto : list){
                dto.setCreatePerson(getUsernameByIdAndUserType(dto.getUserId(), dto.getUserType()));
                if (dto.getRejectUserId() != null){
                    dto.setRejectPerson(getUsernameByIdAndUserType(dto.getRejectUserId(), dto.getRejectUserType()));
                }
            }
            APPResultMessage<Object, ProjectFileDTO> message = APPResultMessage.getSuccessMessage();
            message.setResult(result);
            return message;
        }
    }

    @Transactional
    public APPResultMessage doAddProjectFile(MultipartFile file, Integer projectId, Integer fileType, String remark, Integer userId, Short userType) throws Exception{

        Integer stageId = 0;
        if(fileType == 5123){
            MjProjectStage stage = projectStageMapper.selectOne(
                    new LambdaQueryWrapper<MjProjectStage>()
                            .eq(MjProjectStage::getProjectId, projectId)
                            .eq(MjProjectStage::getIsCurrent, 1)
            );
            if(!stage.getCode().equals(ProjectStatusEnum.PACKAGE_CONFIRMING.getCode())){
                MjProjectStage mjProjectStage = new MjProjectStage();


                mjProjectStage.setProjectId(projectId);
                mjProjectStage.setIsCurrent(true);
                mjProjectStage.setName(ProjectStatusEnum.PACKAGE_CONFIRMING.getName());
                mjProjectStage.setCode(ProjectStatusEnum.PACKAGE_CONFIRMING.getCode());
                mjProjectStage.setSort(stage.getSort() + 1);
                mjProjectStage.setCreateTime(new Date());

                stage.setIsCurrent(false);
                stage.setEndTime(new Date());

                projectStageMapper.insert(mjProjectStage);
                projectStageMapper.updateById(stage);
                stageId = mjProjectStage.getId();
            }
        }


//        if(fileType == 5089){
//            MjProjectStage stage = projectStageMapper.selectOne(
//                    new LambdaQueryWrapper<MjProjectStage>()
//                            .eq(MjProjectStage::getProjectId, projectId)
//                            .eq(MjProjectStage::getIsCurrent, 1)
//            );
//            if(!stage.getCode().equals(ProjectStatusEnum.CONTRACTING.getName())){
//                MjProjectStage mjProjectStage = new MjProjectStage();
//
//
//                mjProjectStage.setProjectId(projectId);
//                mjProjectStage.setIsCurrent(true);
//                mjProjectStage.setName(ProjectStatusEnum.SIGNED.getName());
//                mjProjectStage.setCode(ProjectStatusEnum.SIGNED.getCode());
//                mjProjectStage.setSort(stage.getSort() + 1);
//                mjProjectStage.setCreateTime(new Date());
//
//                stage.setIsCurrent(false);
//                stage.setEndTime(new Date());
//
//                projectStageMapper.insert(mjProjectStage);
//                projectStageMapper.updateById(stage);
//                stageId = mjProjectStage.getId();
//
//            }
//        }

        String linuxPath = GlobalStatic.uploadProjectFilePath; // "/home/checkorder/project/";
        String filePath = GlobalStatic.viewProjectFilePath; // "https://checkorder-view.mejour.cn/project/";
        SysLabelValue sysLabelValue = sysLabelValueMapper.selectByPrimaryKey(fileType);
        if (sysLabelValue != null && StringUtil.isNotBlank(sysLabelValue.getDesc())){
            linuxPath = linuxPath + projectId + File.separator + sysLabelValue.getDesc() + File.separator;
            filePath = filePath + projectId + File.separator + sysLabelValue.getDesc() + File.separator;
        }else {
            // 如果没有配置
            linuxPath = linuxPath + projectId + File.separator + "otherFileType" + File.separator;
            filePath = filePath + projectId + File.separator + "otherFileType" + File.separator;
        }
        String fileName = file.getOriginalFilename();  // 文件名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));  // 后缀名
        fileName = StringUtil.generateOrderId() + suffixName; // 新文件名
        String path = linuxPath + File.separator + fileName;
        File dest = new File(path);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        file.transferTo(dest);
        String finalPath = filePath + fileName;

        ProjectFile projectFile = new ProjectFile();
        projectFile.setUserId(userId);
        projectFile.setUserType(userType);
        projectFile.setProjectId(projectId);
        projectFile.setFileType(fileType);
        projectFile.setFileName(ExcelUtils.getFileName(file));
        projectFile.setFilePath(finalPath);
        projectFile.setDelStatus((short) 1);
        projectFile.setCreateTime(new Date());
        projectFile.setRemark(remark);
        projectFile.setRejectStatus((short) 1);
        projectFile.setLinuxPath(path);
        if ( fileType == 5123){
            projectFile.setStageId(
                    (projectFile.getStageId() == null || projectFile.getStageId().trim().isEmpty())
                            ? String.valueOf(stageId)
                            : Stream.concat(
                                    Arrays.stream(projectFile.getStageId().split(",")).map(String::trim),
                                    Stream.of(String.valueOf(stageId))
                            )
                            .filter(s -> !s.isEmpty())
                            .distinct()
                            .collect(Collectors.joining(","))
            );
        }

//        fileMapper.insertSelective(projectFile);
        fileMapper.insert(projectFile);
        if (fileType == 5089 || fileType == 5123 || fileType == 5090){
            // 5089-合同，5123-配包，5090-资质
            // 通知
            String templateCode = "";
            if (fileType == 5089){
                templateCode = "contract";
            } else if (fileType == 5123) {
                templateCode = "package";
            } else if (fileType == 5090) {
                templateCode = "qualification";
            }
            if (StringUtil.isNotBlank(templateCode)){
                Map<String, Object> templateParams = new HashMap<>();
                notifyService.doSendNotifyByRoleId(userId, userType, templateCode, templateParams, projectId);
            }
        }
        return APPResultMessage.getSuccessMessage();
    }

    public APPResultMessage doRejectFile(Integer id, String rejectReason, Integer userId, Short userType) {
        fileMapper.updateRejectById(id, rejectReason, userId, userType);
        ProjectFile projectFile = fileMapper.selectByPrimaryKey(id);
        if (projectFile.getFileType() == 5089 || projectFile.getFileType() == 5123){
            // 5089-合同，5123-配包
            Integer fileType = projectFile.getFileType();
            // 通知
            String templateCode = "";
            if (fileType == 5089){
                templateCode = "rejectContract";
            } else if (fileType == 5123) {
                templateCode = "rejectPackage";
            }
            if (StringUtil.isNotBlank(templateCode)){
                Map<String, Object> templateParams = new HashMap<>();
                notifyService.doSendNotifyByRoleId(userId, userType, templateCode, templateParams, projectFile.getProjectId());
            }
        }
        return APPResultMessage.getSuccessMessage();
    }


    public APPResultMessage rePackage(Integer projectId, String rejectReason, Integer userId, Short userType) {

        MjProject mjProject = projectMapper.selectById(projectId);
        Integer stageId = null;
        MjProjectStage stage = projectStageMapper.selectOne(
                new LambdaQueryWrapper<MjProjectStage>()
                        .eq(MjProjectStage::getProjectId, projectId)
                        .eq(MjProjectStage::getIsCurrent, 1)
        );
        String reason = "配包已被驳回，驳回理由为：" +  rejectReason + "请重新配包！";
        if(!stage.getCode().equals(ProjectStatusEnum.WAIT_PACKAGE.getCode())) {
            MjProjectStage mjProjectStage = new MjProjectStage();
            mjProjectStage.setProjectId(projectId);
            mjProjectStage.setIsCurrent(true);
            mjProjectStage.setName(ProjectStatusEnum.WAIT_PACKAGE.getName());
            mjProjectStage.setCode(ProjectStatusEnum.WAIT_PACKAGE.getCode());
            mjProjectStage.setSort(stage.getSort() + 1);
            mjProjectStage.setCreateTime(new Date());
            mjProjectStage.setRemark(reason);

            stage.setIsCurrent(false);
            stage.setEndTime(new Date());

            projectStageMapper.insert(mjProjectStage);
            projectStageMapper.updateById(stage);
            stageId = mjProjectStage.getId();
        }
        MjProjectStageLog mjProjectStageLog = new MjProjectStageLog();
        mjProjectStageLog.setProjectId(projectId);
        mjProjectStageLog.setStageId(stageId);
        mjProjectStageLog.setUserId(userId);
        mjProjectStageLog.setText(reason);
        return APPResultMessage.getSuccessMessage();
    }


    public String getUsernameByIdAndUserType(Integer userId, Short userType){
        String name = "";
        if(userType == 1){
            // 小程序用户
            MjNormalUser normalUser = normalUserMapper.selectByPrimaryKey(userId);
            name = normalUser.getNickName();
        }else if (userType == 3){
            // 商务
            MjBusinessPerson businessPerson = businessPersonMapper.selectByPrimaryKey(userId);
            name = businessPerson.getUsername();
        }else {
            // 后台账户
            SysManagerUser managerUser = managerUserMapper.selectByPrimaryKey(userId);
            name = managerUser.getUsername();
        }
        return name;
    }

    public ResponseEntity<byte[]> downloadFile(String resourceUrl) {
        try {
            // 从URL获取资源
            URL url = new URL(resourceUrl);
            URLConnection connection = url.openConnection();
            InputStream inputStream = connection.getInputStream();

            // 读取输入流到字节数组
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            byte[] data = outputStream.toByteArray();

            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            // 设置内容类型为二进制流
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

            return new ResponseEntity<>(data, headers, HttpStatus.OK);
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @Transactional
    public APPResultMessage doSureFinalFile(Integer id, int userId, short userType) {



        ProjectFile projectFile = fileMapper.selectByPrimaryKey(id);

        //创建阶段
        MjProjectStage stage = projectStageMapper.selectOne(
                new LambdaQueryWrapper<MjProjectStage>()
                        .eq(MjProjectStage::getProjectId, projectFile.getProjectId())
                        .eq(MjProjectStage::getIsCurrent, 1)
        );
        if(!stage.getCode().equals(ProjectStatusEnum.CONTRACTING.getCode())){
            MjProjectStage mjProjectStage = new MjProjectStage();

            mjProjectStage.setProjectId(projectFile.getProjectId());
            mjProjectStage.setIsCurrent(true);
            mjProjectStage.setName(ProjectStatusEnum.CONTRACTING.getName());
            mjProjectStage.setCode(ProjectStatusEnum.CONTRACTING.getCode());
            mjProjectStage.setSort(stage.getSort() + 1);
            mjProjectStage.setCreateTime(new Date());
            projectStageMapper.insert(mjProjectStage);
            stage.setIsCurrent(false);
            stage.setEndTime(new Date());
            projectStageMapper.updateById(stage);
        }

        // 判断该文件类型下有无其他已确认最终的文件
        ProjectFile file = fileMapper.selectMsgByFileTypeAndNoId(id, projectFile.getFileType(), projectFile.getProjectId());
        if (null != file){
            return new APPResultMessage(6001, "该文件类型已存在终版文件");
        }
        fileMapper.updateFinalById(id, userId, userType);
        fileMapper.updateFinalUpdateTypeByProjectIdAndType(projectFile.getProjectId(), projectFile.getFileType(), (short) 2);
        if (projectFile.getFileType() == 5089 || projectFile.getFileType() == 5123){
            // 5089-合同，5123-配包
            Integer fileType = projectFile.getFileType();
            // 通知
            String templateCode = "";
            if (fileType == 5089){
                templateCode = "sureFinalContract";
            } else if (fileType == 5123) {
                templateCode = "sureFinalPackage";
            }
            if (StringUtil.isNotBlank(templateCode)){
                Map<String, Object> templateParams = new HashMap<>();
                notifyService.doSendNotifyByRoleId(userId, userType, templateCode, templateParams, projectFile.getProjectId());
            }
        }
        return APPResultMessage.getSuccessMessage();
    }

    public APPResultMessage doChannelFinalFile(Integer id, int userId, short userType) {
        fileMapper.updateChannelFinalId(id, userId, userType);
        ProjectFile projectFile = fileMapper.selectByPrimaryKey(id);
        fileMapper.updateFinalUpdateTypeByProjectIdAndType(projectFile.getProjectId(), projectFile.getFileType(), (short) 1);
        if (projectFile.getFileType() == 5089 || projectFile.getFileType() == 5123){
            // 5089-合同，5123-配包
            Integer fileType = projectFile.getFileType();
            // 通知
            String templateCode = "";
            if (fileType == 5089){
                templateCode = "channelFinalContract";
            } else if (fileType == 5123) {
                templateCode = "channelFinalPackage";
            }
            if (StringUtil.isNotBlank(templateCode)){
                Map<String, Object> templateParams = new HashMap<>();
                notifyService.doSendNotifyByRoleId(userId, userType, templateCode, templateParams, projectFile.getProjectId());
            }
        }
        return APPResultMessage.getSuccessMessage();
    }

    public APPResultMessage getFinalFile(FileIdReq req, int userId, short userType) {
        ProjectFile file = fileMapper.selectOne(
                new LambdaQueryWrapper<ProjectFile>()
                        .eq(ProjectFile::getProjectId, req.getProjectId())
                        .eq(ProjectFile::getFileType, req.getFileType())
                        .eq(ProjectFile::getFinalType,2)
        );
        APPResultMessage message = APPResultMessage.getSuccessMessage();
        ResultMessage result = ResultMessage.builder().setData(file);

        message.setResult(result);
        return message;
    }
}
